<template>
  <div class="yd-select">
    <div class="inner-box">
      <!-- <label
        v-if="!filterable"
        class="label"
        :style="[label?'color:#333':'']"
      >{{label?label:placeholder}}</label>-->
      <!-- 搜索 -->
      <input
        v-if="filterable"
        class="input"
        v-model="filterKeyword"
        type="text"
        :placeholder="placeholder"
        @focus="expand=true"
        @blur="handleFilterBlur"
      />
      <!-- 常规 -->
      <input
        v-else
        readonly="readonly"
        class="input"
        v-model="label"
        type="text"
        :placeholder="placeholder"
        @click="handleExpand"
        @blur="expand=false"
        @mouseover="iconClean_show=true"
        @mouseout="iconClean_show=false"
      />
      <!-- 图标 -->
      <template v-if="clearable">
        <span v-show="!iconClean_show" :class="['icon-select',expand?'expand':'']">&gt;</span>
        <span
          v-show="iconClean_show"
          class="icon-clean"
          @mouseover="iconClean_show=true"
          @click.stop="handleClean"
        >x</span>
      </template>
      <template v-else>
        <span :class="['icon-select',expand?'expand':'']">&gt;</span>
      </template>
    </div>
    <!-- 展开面板 -->
    <transition name="expand">
      <div class="expand-box" v-show="expand" ref="expandInstance">
        <slot></slot>
        <div v-show="optionShowCount<=0" class="nullData-tips">无数据~</div>
      </div>
    </transition>
  </div>
</template>

<script>
import { reactive, toRefs, getCurrentInstance, onMounted, watch } from "vue";
export default {
  name: "yd-select",
  props: {
    modelValue: [String, Number],
    filterable: {
      type: Boolean,
      default: false
    },
    clearable: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: "请选择"
    }
  },
  setup(props, ctx) {
    const state = reactive({
      expand: false,
      label: "",
      iconClean_show: false,
      filterKeyword: "",
      optionShowCount: 0
    });
    const instance = getCurrentInstance();
    try {
      state.optionShowCount = instance.slots.default()[0].children.length;
    } catch (error) {
      state.optionShowCount = 0;
    }
    const handleSetOptionCount = add => {
      if (add) {
        state.optionShowCount = instance.slots.default()[0].children.length;
      } else {
        state.optionShowCount--;
        if (state.optionShowCount < 0) {
          state.optionShowCount = 0;
        }
      }
    };

    const handleExpand = () => {
      state.expand = !state.expand;
    };
    const handleSetValue = data => {
      ctx.emit("update:modelValue", data.value);
      ctx.emit("change", data.value);
      state.label = data.label;
      if (props.filterable) {
        state.filterKeyword = data.label;
      }
      state.expand = false;
    };
    const handleClean = () => {
      state.label = "";
      ctx.emit("update:modelValue", "");
      ctx.emit("clear");
    };
    const handleFilterBlur = () => {
      setTimeout(() => {
        state.filterKeyword = state.label;
      }, 100);
      if (!state.filterKeyword) {
        ctx.emit("update:modelValue", "");
      }
      state.expand = false;
    };
    const initLabel = () => {
      let obj = {};
      instance.slots.default &&
        Array.isArray(instance.slots.default()[0].children) &&
        instance.slots.default()[0].children.map(item => {
          obj[item.props.value] = item.props.label;
        });

      state.label = obj[props.modelValue]
        ? obj[props.modelValue]
        : props.modelValue;
    };
    onMounted(() => {
      initLabel();
    });

    return {
      ...toRefs(state),

      initLabel,
      handleExpand,
      handleSetValue,
      handleClean,
      handleFilterBlur,
      handleSetOptionCount
    };
  }
};
</script>

<style lang="scss" scoped>
.yd-select {
  position: relative;
  width: 240px;
  height: 40px;
  cursor: pointer;
  .inner-box {
    position: absolute;
    width: 100%;
    height: 100%;
    z-index: 1;
    .input {
      cursor: pointer;
      width: 100%;
      height: 100%;
      padding: 0 15px;
      box-sizing: border-box;
      background-color: #fff;
      border: 1px solid #c0c4cc;
      border-radius: 5px;
      outline: none;
      transition: all 0.2s linear;
      &:focus {
        border-color: #409eff;
      }
    }
    .label {
      position: absolute;
      left: 15px;
      top: 0;
      bottom: 0;
      margin: auto;
      color: #c0c4cc;
      font-size: 14px;
      height: 20px;
      line-height: 18px;
    }
    .icon-select {
      position: absolute;
      height: 20px;
      line-height: 18px;
      padding: 0 12px;
      right: 0;
      top: 0;
      bottom: 0;
      margin: auto;
      color: #999;
      transform: rotate(0);
      transition: all 0.2s;
    }
    .expand {
      transform: rotate(90deg);
    }
    .icon-clean {
      position: absolute;
      width: 12px;
      height: 12px;
      line-height: 9px;
      text-align: center;
      font-size: 12px;
      right: 10px;
      top: 0;
      bottom: 0;
      margin: auto;
      color: #c2cadb;
      border: 1px solid #c2cadb;
      border-radius: 50%;
    }
  }
  .expand-box {
    position: absolute;
    width: 100%;
    left: 0;
    top: 100%;
    margin-top: 4px;
    padding: 6px 0;
    width: 100;
    background-color: #fff;
    box-shadow: 0 0 10px #ddd;
    border-radius: 5px;
    cursor: pointer;
    z-index: 2;
    .nullData-tips {
      font-size: 14px;
      color: #999;
      text-align: center;
      height: 30px;
      line-height: 30px;
    }
  }
}

//动画
.expand-enter-active {
  animation: expand 0.2s;
}
.expand-leave-active {
  animation: expand 0.2s reverse;
}

@keyframes expand {
  0% {
    opacity: 0;
    transform: translateY(-10%);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}
</style>